package com.lxh.platform.jdk;

import org.springframework.util.FileCopyUtils;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @create: 2021-08-24 13:42
 * @author: xiaoh.luo001@bkjk.com
 * @description:
 **/
public class MyProxy {

    private static final String rt = "\r";
    private static final String nt = "\t";

    public static Object newProxyInstance(MyClassLoader loader, Class<?> interfaces, MyInvocationHandler h) throws IllegalArgumentException {
        if (h == null) {
            throw new NullPointerException();
        }
        //根据接口构造代理类: $MyProxy0
        Method[] methods = interfaces.getMethods();
        StringBuffer proxyClassString = new StringBuffer();
        proxyClassString.append("package ")
                .append(loader.getProxyClassPackage()).append(";").append(rt).append(rt)
                .append("import java.lang.reflect.Method;").append(rt).append(rt)
                .append("public class $MyProxy0 implements ").append(interfaces.getName()).append("{").append(rt)
                .append(nt).append("MyInvocationHandler h;").append(rt)
                .append(nt).append("public $MyProxy0(MyInvocationHandler h){").append(rt)
                .append(nt).append(nt).append("this.h = h;").append(rt)
                .append(nt).append("}").append(rt)
                .append(getMethodString(methods, interfaces)).append("}");
        //写入java文件 进行编译
        String fileName = loader.getDir() + File.separator + "$MyProxy0.java";
        File myProxyFile = new File(fileName);
        try {
            compile(proxyClassString, myProxyFile);
            //利用自定义的classLoader加载
            Class $myProxy0 = loader.findClass("$MyProxy0");
            //$MyProxy0初始化
            Constructor constructor = $myProxy0.getConstructor(MyInvocationHandler.class);
            return constructor.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void compile(StringBuffer proxyClassString, File myProxyFile) throws IOException {

        FileCopyUtils.copy(proxyClassString.toString().getBytes(), myProxyFile);

        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

        StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);

        Iterable javaFileObjects = standardJavaFileManager.getJavaFileObjects(myProxyFile);

        JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, javaFileObjects);

        task.call();

        standardJavaFileManager.close();
    }

    private static String getMethodString(Method[] methods, Class<?> interfaces) {

        StringBuilder methodStringBuffer = new StringBuilder();
        for (Method method : methods) {
            methodStringBuffer.append(nt).append("public void ").append(method.getName()).append("()").append("{ ").append(rt)
                    .append(nt).append(nt).append("try{").append(rt)
                    .append(nt).append(nt).append(nt).append("Method method1 = ").append(interfaces.getName()).append(".class.getMethod(\"").append(method.getName()).append("\", new Class[]{});").append(rt)
                    .append(nt).append(nt).append(nt).append("this.h.invoke(this, method1, null);").append(rt)
                    .append(nt).append(nt).append("} catch(Exception e){").append(rt)
                    .append(nt).append(nt).append(nt).append("e.printStackTrace();").append(rt)
                    .append(nt).append(nt).append("} catch (Throwable throwable) {").append(rt)
                    .append(nt).append(nt).append(nt).append("throwable.printStackTrace();").append(rt)
                    .append(nt).append(nt).append("}").append(rt)
                    .append(nt).append("}").append(rt);
        }
        return methodStringBuffer.toString();
    }
}




















